<?php

namespace youmbe\plupload\src;

use Yii;
use yii\base\Exception;
use yii\base\InvalidParamException;
use yii\helpers\Url;
use yii\helpers\Html;
use yii\helpers\Json;
use yii\helpers\ArrayHelper;
use yii\widgets\InputWidget;

/**
 * Plupload
 *
 * @author emhome <emhome@163.com>
 * @since 2.0
 */
class Plupload extends InputWidget {

    const SIZE_UNIT = 'kb';

    public $htmlOptions = ['class' => 'plupload_wrapper'];
    public $wrapperOptions;
    public $responeElement;
    //上传地址
    public $url;
    public $attachUrl;
    //
    public $browseIcon = 'ionicons ion-android-add';
    public $browseLabel = '<i class="ionicons ion-ios-plus-empty"></i>';
    public $browseOptions;
    //
    public $uploadLabel = 'Upload Files';
    public $uploadOptions = [];
    //
    public $errorContainer;
    public $errorImageUrl = 'error.png';
    //
    public $previewContainer;
    public $previewOptions = ['class' => 'plupload_preview'];
    public $containerOptions = ['class' => 'plupload_container'];
    //
    public $options = [];
    public $autoUpload = true;
    public $showUploadProgress = true;
    public $chunk_size = 0;
    public $events = [];
    public $showUploadFiles = [];
    public $customOptions = [];
    public $resize = [];
    public $ratio = 1;
    private $resizeOptions = [
        'crop' => true,
        'quality' => 100,
    ];
    public $allow_max_nums = 0;

    /**
     * jpg,mp4,pdf
     * @var type 
     */
    public $extensions = "";

    /**
     * @inheritdoc
     */
    public function init() {
        parent::init();
        // Make sure URL is provided
        if (!$this->url) {
            throw new Exception(Yii::t('yii', '{class} must specify "url" property value.', [
                '{class}' => get_class($this)
            ]));
        }

        // Set id of this widget
        if (!isset($this->htmlOptions['id'])) {
            $this->htmlOptions['id'] = $this->getId();
        }
        $id = $this->htmlOptions['id'];

        if (!preg_match(Html::$attributeRegex, $this->attribute, $matches)) {
            throw new InvalidParamException('Attribute name must contain word characters only.');
        }
        $this->attribute = $matches[2];
        $model = $this->model;
        $attribute = $this->attribute;
        $this->name = Html::getInputName($model, $attribute);
        $this->responeElement = Html::getInputId($model, $attribute);
        $this->options['input_name'] = $this->name;

        // 设置选取按钮
        if (!isset($this->browseOptions['id'])) {
            $this->browseOptions['id'] = $id . "_browse";
        }
        if (!isset($this->browseOptions['class'])) {
            $this->browseOptions['class'] = "plupload-btn-browse";
        }

        if (!empty($this->resize)) {
            $this->options['resize'] = ArrayHelper::merge($this->resizeOptions, $this->resize);
        }

        if ($this->errorImageUrl !== false) {
            $this->options['error_image_url'] = $this->errorImageUrl;
        }

        Html::addCssClass($this->htmlOptions, 'plupload_one');
        $this->setWrapperStyle();
        $this->allow_max_nums = 1;

        // 预览
        if (!isset($this->previewOptions['id'])) {
            $this->previewOptions['id'] = $id . "_preview";
        }
        $this->previewContainer = $id . "_preview";

        // 设置选取按钮
        if (!isset($this->containerOptions['id'])) {
            $this->containerOptions['id'] = $id . "_container";
        }

        if (!$this->autoUpload) {
            if (!isset($this->uploadOptions['id'])) {
                $this->uploadOptions['id'] = $id . "_upload";
            }
            if (!isset($this->uploadOptions['class'])) {
                $this->uploadOptions['class'] = "plupload-btn-upload";
            }
        }

        if (!isset($this->errorContainer)) {
            $this->errorContainer = $id . "_error";
        }

        $this->registerAssets();
    }

    /**
     * @inheritdoc
     */
    public function run() {
        parent::run();
        echo $this->renderPlupload();
    }

    /**
     * Renders the date picker widget.
     */
    protected function renderPlupload() {
        $options = [
            'allow_max_nums' => $this->allow_max_nums,
            'containerOptions' => $this->containerOptions,
            'previewOptions' => $this->previewOptions,
            'errorContainer' => $this->errorContainer,
            'browseLabel' => $this->browseLabel,
            'browseOptions' => $this->browseOptions,
            'autoUpload' => $this->autoUpload,
            'uploadLabel' => $this->uploadLabel,
            'uploadOptions' => $this->uploadOptions,
            'htmlOptions' => $this->htmlOptions,
            'attachUrl' => $this->attachUrl,
        ];
        if ($this->hasModel()) {
            $options['model'] = $this->model;
            $options['attribute'] = $this->attribute;
        }
        return $this->render('single', $options);
    }

    /**
     * Registers the needed assets
     */
    public function registerAssets() {
        $this->registerAssetBundle();
        $view = $this->getView();
        $options = [
            'id' => Html::getInputId($this->model, $this->attribute),
            'inputName' => $this->name,
            'authFilter' => '',
            'multiSelection' => false,
            'url' => 'http://oss.aliyuncs.com',
            'maxFileSize' => '1000mb',
            'mimeTypes' => $this->formatMimeType(),
            'ratio' => $this->ratio,
        ];
        $view->registerJs('$("#' . $this->id . '").uploader(' . Json::encode($options) . ');');
    }

    public function formatMimeType() {
        $extensions = $this->extensions;
        if (is_string($extensions)) {
            $extensions = array_filter(preg_split("/[\s,]+/", $extensions));
        }
        $mimes = [
            'jpg' => 'image',
            'gif' => 'image',
            'png' => 'image',
            'bmp' => 'image',
            'zip' => 'zip',
            'rar' => 'zip',
            'mp4' => 'video',
            'wav' => 'audio',
            'pdf' => 'pdf',
        ];
        $mimeTypes = [];
        if (!empty($extensions)) {
            foreach ($extensions as $ext) {
                if (!isset($mimes[$ext])) {
                    continue;
                }
                $mimeTypes[$mimes[$ext]][] = $ext;
            }
        } else {
            foreach ($mimes as $ext => $type) {
                $mimeTypes[$type][] = $ext;
            }
        }

        $data = [];
        foreach ($mimeTypes as $mtk => $mtv) {
            $data[] = [
                'title' => ucfirst($mtk) . ' files',
                'extensions' => implode(',', $mtv),
            ];
        }
        return $data;
    }

    /**
     * Registers the asset bundle and locale
     */
    public function registerAssetBundle() {
        return BasePluginAsset::register($this->view);
    }

    /**
     * Registers the asset bundle and locale
     */
    protected function buildCallbackEvent() {
        $events = ArrayHelper::merge(self::buildEvents(), $this->events);
        if (empty($events)) {
            return;
        }
        $script = '';
        foreach ($events as $event => $callback) {
            $script .= $this->id . ".bind('$event', $callback);\n";
        }
        return $script;
    }

    /**
     * buildEvents
     * Generate event JavaScript
     */
    protected function buildEvents() {
        $registerEvents = [
            'Init',
            'PostInit',
            'FilesAdded',
            'FilesRemoved',
            'BeforeUpload',
            'FileUploaded',
            'UploadComplete',
            'Refresh',
            'Error'
        ];
        //是否显示上传进度
        if ($this->showUploadProgress) {
            $registerEvents[] = 'UploadProgress';
        }
        //register script of plupload evnets
        $configs = [
            'errorContainer' => $this->errorContainer,
            'previewContainer' => $this->previewContainer,
            'uploadOptions' => $this->uploadOptions,
            'autoUpload' => $this->autoUpload,
            'responeElement' => $this->responeElement,
            'attachUrl' => $this->attachUrl,
        ];
//        $event = new PluploadEvents($configs);
//        return $event->getScripts($registerEvents);
    }

    /**
     * 设置样式
     */
    protected function setWrapperStyle() {
        if (isset($this->htmlOptions['style'])) {
            return;
        }
        $width = 480;
        $height = 300;
        if (isset($this->options['resize']) && !empty($resize = $this->options['resize'])) {
            $width = !isset($resize['width']) ?: $resize['width'];
            $height = !isset($resize['height']) ?: $resize['height'];
        }

        if (isset($this->wrapperOptions['width'])) {
            $width = (int) $this->wrapperOptions['width'];
        }
        if (isset($this->wrapperOptions['height'])) {
            $height = (int) $this->wrapperOptions['height'];
        }
        $this->htmlOptions['data-model'] = Html::getInputId($this->model, $this->attribute);
    }

    /**
     * @return int the max upload size in MB
     */
    protected function getUploadMaxSize() {
        $upload_max_filesize = (int) (ini_get('upload_max_filesize'));
        $post_max_size = (int) (ini_get('post_max_size'));
        $memory_limit = (int) (ini_get('memory_limit'));
        return min($upload_max_filesize, $post_max_size, $memory_limit) . 'mb';
    }

    /**
     * 分块大小
     */
    protected function getChunkSize() {
        $chunksize = (int) $this->chunk_size;
        if ($chunksize) {
            return $chunksize . self::SIZE_UNIT;
        }
        return $chunksize;
    }

}
